iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 16
0
自我挑戰組

學JS的心路歷程系列 第 16

學JS的心路歷程 Day16-Promise(一)

  • 分享至 

  • xImage
  •  

今天在進入 Promise 程式碼之前,我們先來用個例子來解釋 Promise 是什麼。

未來值

假設我們今天來到速食店,點了一個漢堡,付錢給店員。
點了餐點並付費,可以理解為我們發送了一個請求,希望得到一個回傳值(也就是漢堡)。

不過常見情況是,漢堡還沒做好,不能立即給我,店員給了我一張收據上面寫著點餐號碼。這個點餐號碼是一種「我欠你」的承諾( promise ),確保我最後能夠拿到我的漢堡。

所以只要拿著收據,我就能確保我未來的漢堡,不需要去擔心。這樣在等待的同時我就能夠做其他事情,像是滑手機。

直到店員喊了我的號碼,我拿著我的收據到櫃台給店員換得了我的漢堡。
換句話說,一旦未來值準備就緒,我就能夠用手上對值的承諾( value-promise )交換那個值本身。
但還有另一種結果,就是叫了我的號碼,我走過去後店員跟我說 漢堡賣完了。
這時候我們可以看到未來值一個重要的特性:代表成功,也可能代表失敗。

也就是說 Promise 物件的設計就是針對異步函式的執行結果所設計的,最後的結果要不然就用一個回傳值來 fulfilled (實現),要不然就用一個理由(錯誤)來 rejected (拒絕)。

那到底要怎麼用呢?首先我們要先建立一個 Promise 物件:

var promise = new Promise(function(resolve, reject) {
  // 成功時
  resolve(value)
  // 失敗時
  reject(reason)
});

promise.then(function(value) {
  // on fulfillment(已實現時)
}, function(reason) {
  // on rejection(已拒絕時)
})

建構式傳入參數需要一個函式,稱為 executor 有強烈執行的意味,當傳入這個函式時,會在建構式回傳物件實體前立即執行,也就是說 Promise 會立即決定裡面的狀態,resolvereject ,兩者都必須是函式類型。
成功執行 resolve(value) 而 Promise 物件的狀態會跑到 fulfilled 狀態固定住;
失敗或是發生錯誤時執行 reject(reason) 而 Promise 物件的狀態會跑到 rejected 狀態固定住。

也因為與一般物件實體化過程不太一樣,所以通常會先包在一個函式中,需要使用時再呼叫函式來產生 Promise 物件:

function generatePromise(value) {
    return new Promise(function(resolve, reject){
        if(value)
            resolve(value) // 已實現,成功
        else
            reject(reason) // 有錯誤,已拒絕,失敗
    });
}

再來剛剛上面範例有看到說 promise 後面接著 then 。那 then 是什麼呢?

then

then 在 Promise 標準中是一個重要的方法,代表「然後、接著或接下來」的意思。then 方法物件被稱為 thenable 物件,我們來看個範例:

promise.then(onFulfilled, onRejected);

promise.then(function(value) {
   // fulfillment
  }, function(reason) {
  // rejection
});

then 一樣用兩個函式當作參數傳入, onFulfilledonRejectedonFulfilled 是當 Promise 物件狀態轉為 fulfilled 時呼叫的函式,會有一個傳入參數值 value 可用; onRejected 則是 Promise 物件狀態轉為 rejected 時呼叫,會有一個傳入參數值 reason 可用。

而在最後, then 會回傳另一個「新的 Promise 物件」。

講了那麼多概念上的東西是不是令人難以理解?沒關係,這邊用個實際範例來講解:

var promise = new Promise(function(resolve, reject) {
  resolve(1)
})

promise
.then(function(value) {
  console.log(value) // 1
  return value + 1
})
.then(function(value) {
  console.log(value) // 2
})

then 方法中的 onFulfilled 函式,也就是第一個傳入的函式參數,它是有值時使用的函式,經過連鎖的結構,如果要把值往下傳遞,可以用回傳值的方式,讓這個值可以繼續的往下面的 then 方法傳送。

那如果不用 Promise ,直接用 callback 會怎麼樣呢?

function doA(doB){
    doB(1,doC)
}
function doB(val,doC){
    doC(val+1)
}
function doC(val){
    console.log(val);
}
doA(doB);

是不是看起來有點痛苦,而且我們還沒加上如果失敗時的函式呢!

今天就先到這邊,如果有錯誤歡迎留言指正,明天會說明 Promise 失敗時的函式用法!

參考資料 :
你所不知道的 JS 非同步處理與效能
從Promise開始的JavaScript異步生活


上一篇
學JS的心路歷程 Day15 - 非同步執行
下一篇
學JS的心路歷程 Day17-Promise(二)
系列文
學JS的心路歷程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言